﻿namespace ufida.u9.ait.openapi
{
	using System;
	using System.Collections.Generic;
    using System.Data;
    using System.IO;
    using System.Text;
    using System.Web;
    using ufida.u9.ait.openapi.utils;
    using UFSoft.UBF.AopFrame;
    using UFSoft.UBF.Business;
    using UFSoft.UBF.Util.Context;

	/// <summary>
	/// AttachmentSaveSV partial 
	/// </summary>	
	public partial class AttachmentSaveSV 
	{	
		internal BaseStrategy Select()
		{
			return new AttachmentSaveSVImpementStrategy();	
		}		
	}
	
	#region  implement strategy	
	/// <summary>
	/// Impement Implement
	/// 
	/// </summary>	
	internal partial class AttachmentSaveSVImpementStrategy : BaseStrategy
	{
		public AttachmentSaveSVImpementStrategy() { }

		public override object Do(object obj)
		{						
			AttachmentSaveSV bpObj = (AttachmentSaveSV)obj;

            List<RetDTO> retlist = new List<RetDTO>();
            try
            {
                if (bpObj.Data == null || bpObj.Data.Count <= 0)
                    throw new Exception("传入参数为空");
                foreach(var dto in bpObj.Data)
                {
                    List<RetDTO> ret = this.DownFile(dto.EntityFullName, dto.EntityCode, dto.SaveDir,dto.DB);
                    retlist.AddRange(ret);
                }
                return ResultUtils.success(bpObj, bpObj.Data, retlist);
            }
            catch (Exception ex)
            {
                return ResultUtils.error(bpObj, bpObj.Data,ex);
            }
		}

        private class RetDTO
        {
            public string Url { get; set; }
            public string FileName { get; set; }
            public string FileSize { get; set; }
            public string FullName { get; set; }
            public string EntityCode { get; set; }
        }
        /// <summary>
        /// 下载文件到U9服务器,并返回URL访问路径
        /// <param name="fullName">实体全名 UFIDA.U9.AP.Payment.PayReqFundHead</param>
        /// <param name="code">单号或档案编码</param>
        /// <param name="dir">保存路径,相对路径,在U9 Portal目录下</param>
        /// <param name="db">文档库名 U9CEDoc</param>
        /// </summary>
        private List<RetDTO> DownFile(string fullName,string code,string dir,string db)
        {
            BusinessEntity entity = EntityUtils.GetBusinessEntity(fullName, code);
            List<RetDTO> retlist = new List<RetDTO>();
            if (entity == null) throw new Exception($"查找实体失败!实体名:[{fullName}],编码:[{code}]");
            
            //取实体的附件数据
            string sql = $@"select att.EntityFullName,att.EntityID,att.URI,att.Title,att.Size,info.FileName,info.Content
                            from Base_Attachment att
                            join [{db}].dbo.FileInfo info on att.FileHandler=info.ID
                            where att.EntityID={entity.ID}";
            DataSet ds = new DataSet();
            UFSoft.UBF.Util.DataAccess.DataAccessor.RunSQL(UFSoft.UBF.Util.DataAccess.DataAccessor.GetConn(), sql, null, out ds);
            if(ds==null||ds.Tables.Count==0||ds.Tables[0].Rows.Count==0)
                return retlist;
            
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                string fileName = dr["FileName"].ToString();
                string fileSize = dr["Size"].ToString();
                byte[] content = dr["Content"] as byte[];

                //替换文件名中的特殊字符
                string fileNameTrim = FileNameTrim(fileName);
                //string encodedString = FileName2Base64(fileName);

                //文件名相对路径:DownloadAttach/UFIDA.U9.AP.Payment.PayReqFundHead/RE-0002/12285713573305858346.png
                string dir1 = dir + "/" + fullName + "/" + code;
                FileUtils.WriteU9BinFile(dir1, fileNameTrim, content);

                RetDTO retDTO = new RetDTO();
                retDTO.FileName = fileName;
                retDTO.FileSize = fileSize;
                //这里的文件名需要进行URL编码,避免文件名存在URL特殊字符
                //举例:文件名[世界地图高+清%.jpeg]编码后为[世界地图高%2B清%25.jpeg] 
                //retDTO.Url = dir1+"/"+ HttpUtility.UrlEncode(fileName);

                //通过代码Encode,浏览器来Decode,这种方式有问题,还是采用replace特殊字符的方式
                //原因是因为现代浏览器会自动对url进行编码
                //调整:将文件名进行base64处理后保存,不再replace特殊字符
                //base64会导致下载文件为乱码
                retDTO.Url = dir1 + "/" + fileNameTrim;
                retDTO.EntityCode = code;
                retDTO.FullName = fullName;
                retlist.Add(retDTO);
            }

            return retlist;
        }
        /// <summary>
        /// 替换文件名中的特殊字符
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static string FileNameTrim(string fileName)
        {
            //去掉JSON特殊字符
            string fileNameTrim = fileName.Replace("\"", "");
            //下述去掉URL特殊字符
            fileNameTrim = fileNameTrim.Replace("+", "");
            fileNameTrim = fileNameTrim.Replace(" ", "");
            fileNameTrim = fileNameTrim.Replace("/", "");
            fileNameTrim = fileNameTrim.Replace("?", "");
            fileNameTrim = fileNameTrim.Replace("%", "");
            fileNameTrim = fileNameTrim.Replace("#", "");
            fileNameTrim = fileNameTrim.Replace("&", "");
            fileNameTrim = fileNameTrim.Replace("=", "");
            return fileNameTrim;
        }

        /// <summary>
        /// 将文件名进行base64处理,保留扩展名
        /// 进行 Base64 字符串 URL 安全
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static string FileName2Base64(string fileName)
        {
            string fileNameWithoutExt = System.IO.Path.GetFileNameWithoutExtension(fileName);
            string fileExtension = System.IO.Path.GetExtension(fileName);

            // 将文件名主体进行 Base64 编码
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(fileNameWithoutExt);
            string base64Name = Convert.ToBase64String(bytes);

            // 进行 Base64 字符串 URL 安全
            string urlSafeBase64Name = base64Name.Replace('+', '-').Replace('/', '_').TrimEnd('=');

            // 创建新的文件名
            string newFileName = urlSafeBase64Name + fileExtension;
            return newFileName;
        }
    }

	#endregion
	
}